const { Worker } = require("worker_threads");
const path = require("path");
const logger = require("winston");

const now = new Date();
const year = now.getFullYear(); // 获取年份，例如 2025
const month = String(now.getMonth() + 1).padStart(2, "0"); // 获取月份，从 0 开始，需要加 1，并补零
const day = String(now.getDate()).padStart(2, "0"); // 获取日期，并补零

// 配置日志
logger.configure({
  level: "debug",
  transports: [
    new logger.transports.Console({
      level: "info",
      format: logger.format.combine(
        logger.format.timestamp(),
        logger.format.printf(
          (info) => `${info.timestamp} - ${info.level} - ${info.message}`
        )
      ),
    }),
    new logger.transports.File({
      level: "debug",
      filename: `thread_${year}${month}${day}.log`,
      format: logger.format.combine(
        logger.format.timestamp(),
        logger.format.printf(
          (info) => `${info.timestamp} - ${info.level} - ${info.message}`
        )
      ),
      maxsize: 10485760, // 10MB
      maxFiles: 5,
      tailable: true,
    }),
  ],
});

class ThreadPool {
  constructor(size, workerScript) {
    this.size = size;
    this.workerScript = workerScript;
    this.taskQueue = [];
    this.workers = new Array(size).fill(null).map(() => this.createWorker());
  }

  createWorker() {
    const worker = new Worker(path.resolve(__dirname, this.workerScript));
    worker.isBusy = false;

    worker.on("message", (message) => {
      if (message.type === "ready") {
        this.processNextTask(worker);
      }
    });

    worker.on("error", (err) => {
      logger.error(`Worker error: ${err.message}`);
      this.replaceWorker(worker);
    });

    worker.on("exit", (code) => {
      if (code !== 0) {
        logger.error(`Worker stopped with exit code ${code}`);
        this.replaceWorker(worker);
      }
    });

    return worker;
  }

  replaceWorker(oldWorker) {
    const index = this.workers.indexOf(oldWorker);
    if (index !== -1) {
      const newWorker = this.createWorker();
      this.workers[index] = newWorker;
    }
  }

  processNextTask(worker) {
    if (this.taskQueue.length > 0) {
      const task = this.taskQueue.shift();
      worker.isBusy = true;
      worker.postMessage(task);
    } else {
      worker.isBusy = false;
    }
  }

  execute(taskData) {
    return new Promise((resolve, reject) => {
      const availableWorker = this.workers.find((w) => !w.isBusy);

      const taskWrapper = {
        data: taskData,
        resolve,
        reject,
      };

      if (availableWorker) {
        availableWorker.isBusy = true;
        availableWorker.postMessage(taskData);

        availableWorker.once("message", (result) => {
          result.error ? reject(result.error) : resolve(result);
          this.processNextTask(availableWorker);
        });
      } else {
        this.taskQueue.push(taskWrapper);
      }
    });
  }
}

module.exports = ThreadPool;
